/**
 * Copyright (c) 2018-2022, NXOS Development Team
 * SPDX-License-Identifier: Apache-2.0
 * 
 * Contains: divide
 * 
 * Change Logs:
 * Date           Author            Notes
 * 2022-08-17     JasonHu           Port from xboot
 */

#ifndef __UTILS_DIV_H__
#define __UTILS_DIV_H__

#include <nxos_mini.h>

#define __DoAbs(x)	((x) < 0 ? -(x) : (x))

extern NX_U32 __UDiv32(NX_U32 dividend, NX_U32 divisor, NX_U32 * remainder);
extern NX_U64 __UDiv64(NX_U64 dividend, NX_U64 divisor, NX_U64 * remainder);

static inline NX_U32 NX_UDiv32(NX_U32 value, NX_U32 divisor)
{
	NX_U32 r;
	return __UDiv32(value, divisor, &r);
}

static inline NX_U32 NX_UMod32(NX_U32 value, NX_U32 divisor)
{
	NX_U32 r;

	__UDiv32(value, divisor, &r);
	return r;
}

static inline NX_I32 NX_SDiv32(NX_I32 value, NX_I32 divisor)
{
	NX_U32 r;

	if((value * divisor) < 0)
    {
		return -__UDiv32(__DoAbs(value), __DoAbs(divisor), &r);
    }
	else
    {
		return __UDiv32(__DoAbs(value), __DoAbs(divisor), &r);
    }
}

static inline NX_I32 NX_SMod32(NX_I32 value, NX_I32 divisor)
{
	NX_U32 r;

	__UDiv32(__DoAbs(value), __DoAbs(divisor), &r);
	
    return (value < 0) ? -r : r;
}

static inline NX_U64 NX_UDiv64(NX_U64 value, NX_U64 divisor)
{
	NX_U64 r;
	return __UDiv64(value, divisor, &r);
}

static inline NX_U64 NX_UMod64(NX_U64 value, NX_U64 divisor)
{
	NX_U64 r;

	__UDiv64(value, divisor, &r);
	return r;
}

static inline NX_I64 NX_SDiv64(NX_I64 value, NX_I64 divisor)
{
	NX_U64 r;

	if((value * divisor) < 0)
    {
		return -__UDiv64(__DoAbs(value), __DoAbs(divisor), &r);
    }
	else
    {
		return __UDiv64(__DoAbs(value), __DoAbs(divisor), &r);
    }
}

static inline NX_I64 NX_SMod64(NX_I64 value, NX_I64 divisor)
{
	NX_U64 r;

	__UDiv64(__DoAbs(value), __DoAbs(divisor), &r);

    return (value < 0) ? -r : r;
}

#endif /* __UTILS_DIV_H__ */
